[iOS] Social Framework の「SLRequest」を使って Twitter に投稿する
はじめに
こんにちは。モバイルアプリサービス部の平屋です。
本記事では、Social Framework の「SLRequest」クラスを使って Twitter に投稿する手順を紹介します。
SLComposeViewController と SLRequest
前回の記事「[iOS] 標準コンポーネント「SLComposeViewController」を使って Twitter や Facebook に投稿する」では、Social Framework の「SLComposeViewController」クラスを使って Twitter/Facebook に投稿させる方法を紹介しました。
「SLComposeViewController」クラスを使えば、ほんの少しのコードを追加するだけで SNS へ投稿する機能を提供できますが、以下の場合は「SLComposeViewController」クラスを使えません。
- カスタムの投稿画面を使いたい
- ユーザーの代わりに投稿したい
上記の場合は、以下のような方法で投稿機能を実装する必要があります。
- Social Framework の SLRequest クラスを使う
- Fabric の Twitter Kit を使う
- Twitter の REST API にアクセスするクラスを自作して使う
本記事では Social Framework の「SLRequest」クラスを使って Twitter に投稿する方法を紹介します。
サンプルアプリについて
本記事で解説するコードは以下のリポジトリで公開してます。
検証環境
- OS X El Capitan 10.11.4
- Xcode 7.3.1
- 検証した iOS 端末
- iPhone 4s iOS 8.4.1
- iPhone 5s iOS 9.3.1
目次
ACAccountStore を使用してアカウント情報を取得する
前回と同様に、本記事でも OS の「設定アプリ」に設定されている Twitter アカウントを使用します。
まずは、投稿に使用するアカウント情報を取得する実装から見ていきましょう。
ACAccountStore と ACAccountType を作成する
「設定アプリ」に設定されているアカウントの情報を取得するには、Accounts Framework の ACAccountStore
クラスを使用します。また、ACAccountType
はアカウントのタイプに関する情報を保持するクラスであり、次の「ACAccount を取得する」で使用します。
@interface SPDTwitterClient () @property (nonatomic) ACAccountStore *accountStore; @property (nonatomic) ACAccountType *accountType; @end @implementation SPDTwitterClient - (instancetype)init { self = [super init]; if (self) { _accountStore = [ACAccountStore new]; _accountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter]; } return self; } ... @end
ACAccount を取得する
ACAccount
は 1 つのアカウントの情報を保持するクラスです。ACAccountStore
を使用すれば、ACAccount
を取得できます。
まずは、ACAccountStore
の requestAccessToAccountsWithType:options:completion:
メソッドを使用して、アカウントへのアクセスを要求します。
- (void)loadAccountsWithCompletion:(void (^)(NSArray *accounts, NSError *error))completion { [self.accountStore requestAccessToAccountsWithType:self.accountType options:nil completion:^(BOOL granted, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (granted) { NSArray *accounts = [self.accountStore accountsWithAccountType:self.accountType]; completion(accounts, nil); } else { completion(nil, error); } }); }]; }
requestAccessToAccountsWithType:options:completion:
メソッドを初めて呼んだタイミングで以下のアラートが表示されます。「許可しない」または「OK」のどちらかが既に選択されている場合は、アラートは表示されません。
ユーザーがアラート上のボタンをタップすれば、completion
ブロックの中身が実行されます。「OK」がタップされたのであれば、granted
の値が YES
になり、ACAccountStore
の accountsWithAccountType:
メソッドを使用して ACAccount
の配列を取得できます。
Twitter の場合は「設定アプリ」に複数のアカウントを設定できるので、複数の ACAccount
が返ってくる可能性があります。アプリによっては、複数のアカウントの中から 1 つのアカウントを選択させる UI を提供したほうが良いかもしれません。
また、completion
ブロックは任意のキューから呼ばれます。操作完了時に実行されるブロック内で UI を操作する場合は、メインスレッドで処理が実行されるようにしなければなりません。
SLRequest を使用して投稿する
Social Framework の SLRequest
クラスを使用すれば、SNS の API に対する HTTP リクエストを簡単に作成できます。
SLRequest を使用して画像をアップロードする
投稿に画像を添付する場合は、まず「media/upload API」を使用して画像をアップロードします。
- media/upload API
- POST
- https://upload.twitter.com/1.1/media/upload.json
- ドキュメント
SLRequest
の requestForServiceType:requestMethod:URL:parameters:
メソッドを使用して、SLRequest
オブジェクトを作成します。
次に、addMultipartData:withName:type:filename:
メソッドを使用して画像データを追加し、account プロパティに「ACAccountStore を使用してアカウント情報を取得する」で取得した ACAccount
オブジェクトをセットします。
最後に performRequestWithHandler:
メソッドを使用してリクエストを実行します。
- (void)uploadImageWithAccount:(ACAccount *)account image:(UIImage *)image completion:(void (^)(NSString *mediaIdString, NSError *error))completion { SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:@"https://upload.twitter.com/1.1/media/upload.json"] parameters:nil]; [request addMultipartData:UIImageJPEGRepresentation(image, 1.0f) withName:@"media" type:@"image/jpeg" filename:@"image.jpg"]; [request setAccount:account]; [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { completion(nil, error); } else { NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:nil]; NSString *mediaIdString = json[@"media_id_string"]; completion(mediaIdString, nil); } }); }]; }
media/upload API にリクエストを送ると以下のようなレスポンスが返ってきます。media_id_string
は本文投稿時に使用します。
{ "expires_after_secs" = 86400; "image": { "w": 320, "h": 640, "image_type": "image/jpeg" } "media_id": 553639437322563584, "media_id_string": "553639437322563584", "size": 998865, }
SLRequest を使用して本文を投稿する
本文を投稿するには「statuses/update API」を使用します。
- statuses/update API
- POST
- https://api.twitter.com/1.1/statuses/update.json
- ドキュメント
画像アップロードの場合と同様に SLRequest
の requestForServiceType:requestMethod:URL:
メソッドを使用して、SLRequest
オブジェクトを作成します。requestForServiceType:requestMethod:URL:parameters:
の parameters
引数にはパラメータが格納された NSDictionary
をセットします。
- パラメータ用の
NSDictionary
status
キーの値- 本文
media_ids
キーの値 (画像を添付する場合のみ)- 「SLRequest を使用して画像をアップロードする」で取得した
media_id_string
- 「SLRequest を使用して画像をアップロードする」で取得した
次に、account プロパティに ACAccount
オブジェクトをセットします。
最後に performRequestWithHandler:
メソッドを使用してリクエストを実行します。
- (void)postWithAccount:(ACAccount *)account message:(NSString *)message mediaIdString:(NSString *)mediaIdString completion:(void (^)(NSError *error))completion { NSDictionary *parameters = nil; if (mediaIdString) { parameters = @{ @"media_ids" : mediaIdString, @"status" : message }; } else { parameters = @{ @"status" : message }; } SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:@"https://api.twitter.com/1.1/statuses/update.json"] parameters:parameters]; [request setAccount:account]; [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error){ dispatch_async(dispatch_get_main_queue(), ^{ completion(error); }); }]; }
動作結果
画像付きで投稿してみました。
今回は、Twitter にアプリを登録せず、Social Framework のクラスを使用して投稿したので、OS から投稿された扱いになります。
まとめ
本記事では Social Framework の「SLRequest」クラスを使って Twitter に投稿する手順を紹介しました。
今回解説したコードは以下のリポジトリで公開してますので参考にしてみてください。
参考記事
- ACAccountStore Class Reference - developer.apple.com
- SLRequest Class Reference - developer.apple.com
- POST media/upload - dev.twitter.com
- POST statuses/update - dev.twitter.com